package com.example.jetpackcomposelazycolumn.ui.progress

import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.example.jetpackcomposelazycolumn.ui.theme.AppColors.Companion.snow
import com.example.jetpackcomposelazycolumn.ui.theme.MaterialColors.Companion.blue300

@Composable
fun InfiniteProgress(
    modifier: Modifier = Modifier,
    progressColor: Color = blue300,
    progressBackgroundColor: Color = snow,
    strokeWidth: Dp = 10.dp,
    strokeBackgroundWidth: Dp = 10.dp,
    progressDirection: AnimationDirection = AnimationDirection.RIGHT,
    rounderBorder: Boolean = false,
    durationInMilliSecond: Int = 800,
    radius: Dp = 80.dp
) {
    val stroke = with(LocalDensity.current) {
        Stroke(
            width = strokeWidth.toPx(),
            cap = if (rounderBorder) StrokeCap.Round else StrokeCap.Square
        )
    }

    val strokeBackground = with(LocalDensity.current) {
        Stroke(width = strokeBackgroundWidth.toPx())
    }

    val transition = rememberInfiniteTransition()

    val animatedRestart by transition.animateFloat(
        initialValue = 0f,
        targetValue = if (progressDirection == AnimationDirection.RIGHT) 360f else -360f,
        animationSpec = infiniteRepeatable(tween(durationInMilliSecond, easing = LinearEasing))
    )

    Canvas(modifier = modifier.size(radius * 2)) {
        val higherStrokeWidth =
            if (stroke.width > strokeBackground.width) stroke.width else strokeBackground.width
        val radiusTopLeft = (size.minDimension - higherStrokeWidth) / 2
        val halfSize = size / 2.0f
        val topLeft = Offset(halfSize.width - radiusTopLeft, halfSize.height - radiusTopLeft)
        val size = Size(radiusTopLeft * 2, radiusTopLeft * 2)

        drawArc(
            startAngle = 0f,
            sweepAngle = 360f,
            topLeft = topLeft,
            color = progressBackgroundColor,
            useCenter = false,
            size = size,
            style = strokeBackground
        )

        drawArc(
            color = progressColor,
            startAngle = animatedRestart,
            sweepAngle = 90f,
            useCenter = false,
            topLeft = topLeft,
            size = size,
            style = stroke
        )
    }

}

@Preview
@Composable
fun InfiniteProgressPreview() {
    InfiniteProgress(durationInMilliSecond = 1300)
}